
<!-- 用法 -->
<!-- <mytable
:config="{
    isShowStatistics:true,
    isCanSelect:true,
    colWidths:[80,120,120,120,120,120]
}" :data="data" data 需要是 ref    :on-click-row-cb="onClickRowCb"
:title-array="['媒体资源','广告','xx','xx','xxx','xxx']"
></mytable> -->

<template>
    <div class="table">
        <!-- //按列来展示数据 -->
        <div ref="tableRef" class="col-table flex-start">
            <!-- 最左侧一列 -->
            <div ref="colHeadRef" class="col-head" :class="{scroll}">
                <li
                    v-for="(item, idx) in showColData[0]" :key="idx" ref="colHeadLiRefs"
                    :class="[ {active: idx === curSelectIdx},
                              {weight:weightheader && idx === 0} ]"
                    class="col-head-li"
                    @click="onRowClick(idx as number)"
                >
                    {{ item }}
                </li>
            </div>
            <div ref="colbodyRef" class="col-body flex-start">
                <div v-for="(item, index) in showColData.slice(1)" ref="colBodyRefs" :key="index" :class="{isdefinedwidth}" class="col">
                    <li
                        v-for="(subitem, i) in item" :key="i"
                        ref="colBodyLiRefs"
                        :class="[`col_${index + 1}`, {active: i === curSelectIdx},
                                 {weight:(weightheader && i === 0)||(weightdata && +i>0)}
                        ]"
                        @click="onRowClick(i as number)"
                    >
                        {{ formatNumber(subitem) }}
                    </li>
                </div>
            </div>
        </div>
    </div>
</template>

<script lang="ts" setup>

import { numberWithCommas } from '@/utils/filters';
import { watch, ref,onMounted, PropType,toRefs,onUnmounted } from 'vue';

export type colType = string | number;
export type dataType = {
    [key: string]: colType
}
export type titleType = {
    title: string,
}
export type ConfigType = {
    isShowStatistics?: boolean,
    isCanSelect?: boolean,
    ColheadFixedWidth?: number, // 固定第一列的宽度
    isColHeadAverage? : boolean, // 第一列根据 列数来平均
    colWidths?: number[],
    isWeightHeader?:boolean // 是否加重头部显示
    isWeightData?:boolean
}

const props = defineProps({
    titleArray: {
        type: Array as PropType<string[]>,
        required: false,
        default: ()=>{
            return [];
        }
    },
    data: {
        // 请确保data中数据顺序与titleArray对应 这里没有根据属性显示
        type: Array as PropType<dataType[]>,
        required: true,
        default: () => {
            return [];
        }
    },
    config: {
        type: Object as PropType<ConfigType>,
        default: ()=>{
            return {
                isShowStatistics: false,
                isCanSelect: false,
                isColHeadAverage: true,
                colWidths: [],
                focusIndex: 0,
                isWeightHeader: true,
                isWeightData: true
            };
        }
    },
    focusIndex: {
        type: Number,
        default: 0
    },
    onClickRowCb:
    {
        type: Function,
        default: ()=>null
    },
});

const tableRef = ref();
const colHeadRef = ref();
const colBodyRefs = ref([]);
const colbodyRef = ref();

const isdefinedwidth = ref(false);
const scroll = ref(false); // 数据超出时滑动样式绑定类名
const {data,focusIndex} = toRefs(props);
const curSelectIdx = ref(focusIndex);
function setStyle() {

    if(props.config && props.config.colWidths && props.config.colWidths.length>0) {
        // 自定义宽度
        isdefinedwidth.value = true;
        const colHead = colHeadRef.value as HTMLElement;
        if (colHead) {
            colHead.style.width = props.config.colWidths[0] as unknown as string + 'px';
        }
        props.config.colWidths.forEach((item, i) => {
            if (i === 0) {
                return false;
            }
            const colBody =colBodyRefs.value[i - 1] as HTMLElement;
            if (colBody) {
                colBody.style.width = item as unknown as string + 'px';
            }
        });
    } else {
        // 自动计算宽度
        // 设置最左侧一列的宽度 ：

        if(!data.value){
            return;
        }
        if(!data.value.length) {
            return;
        }
        const colHead = colHeadRef.value as HTMLElement;
        const colnum = Object.values(data.value[0]).length;
        const table = tableRef.value as HTMLElement;

        if(!table) {
            return;
        }

        let widthTemp = '375px';
        if (window.getComputedStyle) {
            widthTemp = window.getComputedStyle(table, null).width; // 非IE
        }
        let headColWidth = 0;
        try {
            const tableWidth = parseFloat(widthTemp.slice(0,widthTemp.length - 2));
            headColWidth = tableWidth/colnum;
        } catch (error) {
            headColWidth = 375/colnum;
        } finally {
            if (!colHead) {
                return;
            }
            if(props.config && props.config.ColheadFixedWidth) {
                colHead.style.width = props.config.ColheadFixedWidth as unknown as string + 'px';
            } else if(props.config) {
                if(props.config.isColHeadAverage === undefined || props.config.isColHeadAverage) {
                    // 按列数平均分配
                    colHead.style.width = headColWidth as unknown as string + 'px';
                }
            } else {
                // 完全根据数据自适应宽度
            }
        }
    }
}



let rowData:colType[][]= [];
function onRowClick(colIdx: number) {
    if(!props.config.isCanSelect) {
        return;
    }
    curSelectIdx.value = colIdx;
    props.onClickRowCb(JSON.parse(JSON.stringify(rowData[colIdx])));
}

watch(() => props.config.colWidths, () => {
    setStyle();
}, { immediate: true });

let scollLeft = 0;
function onScroll(){
    const colBody = colbodyRef.value as HTMLElement;
    scollLeft = colBody.scrollLeft;
    scroll.value = !!scollLeft;
}
onMounted(() => {
    setStyle();
    const colBody = colbodyRef.value as HTMLElement;
    scollLeft = colBody.scrollLeft;
    colBody && colBody.addEventListener('scroll',onScroll);
});
onUnmounted(() => {
    const colBody = colbodyRef.value as HTMLElement;
    colBody && colBody.removeEventListener('scroll',onScroll);
});

const statisticsRow: Array<colType> = [];
const showColData = ref<dataType[]>([]);

watch(()=>props.focusIndex,(val:number)=>{
    curSelectIdx.value = val;
});

const weightheader = ref(false);
const weightdata = ref(false);

function setTable(pdata:dataType[]){
    rowData = [];
    const data = pdata;
    setStyle();
    let colNum = 0;
    if (data.length) {
        colNum = Object.values(data[0]).length;
    }
    const tempData = new Array<number>(colNum);
    for (let i = 0; i < tempData.length; i++) {
        tempData[i] = 0;
    }

    statisticsRow.push('合计');
    data.forEach((perData: dataType) => {
        Object.values(perData).forEach((value, i) => {
            if (typeof value === 'number') {
                tempData[i] += value;
            }
        });
    });
    statisticsRow.push(...tempData.slice(1));
    // 顺序不能乱：[title - 合计 - 数据]
    if(props.titleArray.length) {
        rowData.push(props.titleArray);
        weightheader.value = props.config.isWeightHeader?props.config.isWeightHeader:false;
    }
    weightdata.value = props.config.isWeightData?props.config.isWeightData:false;
    if (props.config.isShowStatistics) {
        rowData.push(statisticsRow);
    }
    // 将数据从row转换为col

    const coldata = new Array(colNum); // 以列展示的数据 一个二维数组
    for (let i = 0; i < colNum; i++) {
        coldata[i] = [];
    }
    coldata.forEach((perCol: colType[], i: number) => {
        // 装title
        if (props.titleArray.length) {
            perCol.push(props.titleArray[i]);
        }
        // 将合计的数据统计上
        if (props.config.isShowStatistics) {
            perCol.push(statisticsRow[i]);
        }
        // 遍历装数据
        data.forEach((perData: dataType) => {
            perCol.push(Object.values(perData)[i]);
        });
    });
    // 按行存储数据  --合计之后统计
    data.forEach((perData: dataType) => {
        rowData.push(Object.values(perData));
    });

    showColData.value = coldata as dataType[];
}
setTable(data.value);
watch(() => props.data, (val) => {
    setTable(val);
}, { immediate: true });

const formatNumber = (val: colType) => {
    if (typeof val === 'number') {
        return numberWithCommas(val);
    }
    return val;
};
</script>

<style lang="scss" scoped>
.table {
    width: 100%;
}

.col {
    border-right: 1px solid #eee;
}

li {
    list-style: none;
    box-sizing: border-box;
    padding: 0 10px;
    font-size: 12px;
    height: 36px;
    line-height: 36px;
    color: #333333;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    border-top: 1px solid #eee;
    border: 0;
    border-bottom: 1px solid #eee;
}
li:first-child {
    border-top: 1px solid #eee;
}
li.weight {
    font-weight: 600;
}

li.active {
    background-color: rgba($color: #e60044, $alpha: 5%);
}

.col-table {
    flex-wrap: nowrap;
}

.col-head {
    border-right: 1px solid #eee;
    border-left: 1px solid #eee;
    // text-align: center;
    min-width: 60px;
}
.col-head.scroll {
    box-shadow: -20px 0 15px -23px #ddd inset;
}

.col-body {
    justify-content: flex-start;
    flex: 1;
    flex-wrap: nowrap;
    overflow-x: scroll;
    // text-align: center;
    .col {
        flex: 1;
    }
}
.col.isdefinedwidth {
    flex: auto;
    flex-shrink: 0;
}

.col-body::-webkit-scrollbar {
    display: none;
}

.flex-start {
    display: flex;
    justify-content: flex-start;
    align-items: center;
}
</style>



